/**
 * @file tiny_timer.c
 * @brief 定时器实现
 * @author 张恒宣 
 * @LastEditTime 2025/4/06
 * 
 * MIT License
 *
 * Copyright (c) 2025 张恒宣 luckkeymail@163.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/*********************
 *      头文件
 *********************/

#include "tiny_timer.h"
#include "tiny_malloc.h"
#include "tiny_thread.h"
#include "tiny_rtos_context.h"

/*********************
*     私有变量 
*********************/
static tiny_list_t tiny_timer_list;

/*********************
*      公共函数 
*********************/

/// @brief 定时器初始化
/// @param  无需
void tiny_timer_init(void)
{
		static int is_init = 0;
		if (!is_init)
		{
			tiny_init_list(&tiny_timer_list);
			is_init = 1;
		}		
}

/// @brief 定时器实例初始化
/// @param timer 待初始化的定时器实例
/// @param type  TIMER_ONCE: 触发一次 TIMER_PERIODIC: 周期触发
/// @param interval 触发间隔
/// @param callback 定时回调
/// @param arg 回调参数
/// @note与动态创建定时器不同，静态创建的定时器需要手动初始化
void tiny_timer_obj_init(tiny_timer_t *timer, TIMER_OWNER owner, TIMER_TYPE type, tiny_uint32_t interval, tiny_timer_callback_t callback, void *arg)
{
    if (!timer)
    {
        return;
    }

    timer->type = type;
    timer->status = TIMER_STOPPED;
    timer->timeout = 0;
    timer->interval = interval;
    timer->callback = callback;
    timer->arg = arg;
		timer->timer_owner = owner;
    tiny_init_list_node(&timer->list_link);
}

/// @brief 创建定时器实例
/// @param type TIMER_ONCE: 触发一次 TIMER_PERIODIC: 周期触发
/// @param interval 触发间隔
/// @param callback 定时回调
/// @param arg 回调参数
/// @return 定时器实例
tiny_timer_t *tiny_timer_create(TIMER_TYPE type, tiny_uint32_t interval, tiny_timer_callback_t callback, void *arg)
{
    tiny_timer_t *timer = (tiny_timer_t *)tiny_malloc(sizeof(tiny_timer_t));
    if (!timer)
    {
        return tiny_null;
    }
    tiny_timer_obj_init(timer, TIMER_OWNER_USER, type, interval, callback, arg);
    return timer;
}

/// @brief 删除定时器
/// @param timer 定时器实例
void tiny_timer_delete(tiny_timer_t *timer)
{
    if (!timer)
    {
        return;
    }
    if (timer->status == TIMER_RUNNING)
    {
        tiny_timer_stop(timer);
    }
    tiny_free(timer);
}

/// @brief 设置定时间隔
/// @param timer 定时器实例
/// @param interval 间隔
void tiny_timer_set_interval(tiny_timer_t *timer, tiny_uint32_t interval)
{
    if (timer)
    {
        timer->interval = interval;
    }
}

/// @brief 启动定时器
/// @param timer 定时器实例
void tiny_timer_start(tiny_timer_t *timer)
{
    if (timer && timer->status == TIMER_STOPPED)
    {
        int flag = disable_interrupt();
        timer->status = TIMER_RUNNING;
        timer->timeout = timer->interval + tiny_get_tick_count();
        tiny_list_node_t *node = tiny_timer_list.head;
        if (node == tiny_null)
        {
            tiny_list_insert_pre(&tiny_timer_list, &timer->list_link);
        }
        else
        {
            do
            {
                tiny_timer_t *t = STRUCT_TRANCING_PARENT(node, tiny_timer_t, list_link);
                if (t->timeout > timer->timeout)
                {
                    break;
                }
                node = node->next;
            } while (node != tiny_timer_list.head);

            tiny_insert_pre_list_node(node, &timer->list_link);
            tiny_timer_t *head = STRUCT_TRANCING_PARENT(tiny_timer_list.head, tiny_timer_t, list_link);
            if (head->timeout > timer->timeout)
            {
                tiny_timer_list.head = &timer->list_link;
            }
        }
        enable_interrupt(flag);
    }
}

/// @brief 暂停定时器
/// @param timer 定时器实例
void tiny_timer_stop(tiny_timer_t *timer)
{
    if (!timer)
    {
        return;
    }
    if (timer->status == TIMER_RUNNING)
    {
        int flag = disable_interrupt();
        timer->status = TIMER_STOPPED;
        tiny_remove_node_from_list(&timer->list_link);
        enable_interrupt(flag);
    }
}

/// @brief 定时器检查, 需在任务调度中调用
/// @param  无需
/// @return  TIMER_OWNER
TIMER_OWNER tiny_check_timers(void)
{
		TIMER_OWNER ret = TIMER_OWNER_NONE;
    if (tiny_timer_list.head)
    {
        tiny_timer_t *timer = STRUCT_TRANCING_PARENT(tiny_timer_list.head, tiny_timer_t, list_link);
        if (timer->timeout <= tiny_get_tick_count())
        {
            tiny_timer_stop(timer);
            timer->callback(timer->arg);
            if (timer->type == TIMER_PERIODIC)
            {
                tiny_timer_start(timer);
            }
						
						ret = timer->timer_owner;
        }
    }
		return ret;
}
